﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// 历史记录API
/// </summary>
/// <typeparam name="TVlaue">操作的数据</typeparam>
public class HistoryRecordAPI<TVlaue, TOperation>//Vector2Int, Color32>
{
    /// <summary>
    /// 我们在这里提供了一个参考枚举，你可以使用它
    /// </summary>
    public enum Operation
    {
        /// <summary>
        /// 没有
        /// </summary>
        Not = 0,
        /// <summary>
        /// 添加
        /// </summary>
        Add = 1,
        /// <summary>
        /// 移除
        /// </summary>
        Remove = 2,
        /// <summary>
        /// 修改，置换
        /// </summary>
        Substitution = 3
    };
    /// <summary>
    /// 请输入最大的记录步长
    /// </summary>
    /// <param name="a_MaxStep">最大的记录步长</param>
    public HistoryRecordAPI(int a_MaxStep) 
    {
        mMaxStep = a_MaxStep;
    }

    /// <summary>
    /// 历史记录的集合
    /// </summary>
    List<RecordData> historyRecord = new List<RecordData>(12);

    /// <summary>
    /// 最大的记录步长
    /// </summary>
    int mMaxStep = 99999;
    
    /// <summary>
    /// 当前操作到的步量
    /// </summary>
    int mPointer = 0;

    public int Pointer
    {
        get { return mPointer; }
    }

    public void SetPointer(int pointer)
    {
        mPointer = pointer;
    }

    public List<RecordData> HistoryRecord
    {
        get
        {
            return historyRecord;
        }
    }

    public int MaxStep
    {
        get
        {
            return mMaxStep;
        }
    }

    /// <summary>
    /// 清除一切数据
    /// </summary>
    public void Clear() 
    {
        historyRecord.Clear();
        mPointer = 0;
    }

    /// <summary>
    /// 写入一个历史记录，建议确保这几个集合的长度都相等
    /// </summary>
    /// <param name="a_Operation">操作（添加，删除等）</param>
    /// <param name="a_frontUVList">操作之前的数据</param>
    /// <param name="a_breakUVList">操作之后的数据</param>
    public void Write(TOperation a_Operation, TVlaue a_frontUVList, TVlaue a_breakUVList)
    {
        historyRecord.RemoveRange(mPointer, historyRecord.Count - mPointer);

        RecordData operation = new RecordData(a_Operation);
        operation.m_FrontData = a_frontUVList;
        operation.m_BreakData = a_breakUVList;

        historyRecord.Add(operation);
        if (mPointer >= mMaxStep)
        {
            historyRecord.RemoveAt(0);
        }
        else
        {
            mPointer++;
        }
    }

    /// <summary>
    /// 回滚撤销一步，如果历史记录的后一步操作是没有任何记录的，返回空。 相当于Ctrl + Y
    /// </summary>
    /// <returns>历史记录</returns>
    public RecordData BackRevoke()
    {
        if (mPointer >= historyRecord.Count)
        {
            return null;
        }
        RecordData var_Record = historyRecord[mPointer];
        mPointer++;
        return var_Record;
    }

    /// <summary>
    /// 撤销一步，如果历史记录的前一步是没有任何记录的，返回空。  相当于Ctrl + Z
    /// </summary>
    /// <returns></returns>
    public RecordData Revoke()
    {
        if (mPointer == 0)
        {
            return null;
        }
        mPointer--;
        RecordData var_Record = historyRecord[mPointer];
        return var_Record;
    }

    /// <summary>
    /// 历史数据
    /// </summary>
    /// <typeparam name="T">操作的数据</typeparam>
    public class RecordData
    {
        /// <summary>
        /// 输入一个操作来新建这个历史数据
        /// </summary>
        /// <param name="a_Operation">操作的类型，用int表示.你可以使用VoxelHistoryRecordAPI中我们提供的Operation</param>
        public RecordData(TOperation a_Operation)
        {
            this.mOperation = a_Operation;
            //mFrontData = new List<T>();
            //mBreakUVData = new List<T>();
        }

     
        private TOperation mOperation;
        /// <summary>
        /// 操作（添加，删除等）
        /// </summary>
        public TOperation m_Operation
        {
          get { return mOperation; }
          internal set { mOperation = value; }
        }

        private TVlaue mFrontData;
        /// <summary>
        /// 操作之前的数据
        /// </summary>
        public TVlaue m_FrontData
        {
            get { return mFrontData; }
            internal set { mFrontData = value; }
        }

        private TVlaue mBreakUVData;
        /// <summary>
        /// 操作之后的数据
        /// </summary>
        public TVlaue m_BreakData
        {
            get { return mBreakUVData; }
            internal set { mBreakUVData = value; }
        }
    }
}
